package top.fyukina.fymil.elements;

import top.fyukina.fymil.DataType;
import top.fyukina.fymil.exceptions.OperationDeniedException;
import top.fyukina.fymil.exceptions.VarNotFoundException;
import java.util.Arrays;
import java.util.Stack;
import java.util.function.Function;

/**
 * 没有比这个类更糟糕的设计了
 * 因为这涉及了大量的对象操作，还做得很烂
 */
public class VarDomainStack {
    private final Stack<VarDomain> varDomains;
    public VarDomainStack() {
        varDomains = new Stack<>();
        createVarDomain();
    }
    public void createVarDomain() {
        varDomains.push(new VarDomain());
    }
    public void eraseVarDomain() {
        varDomains.pop();
    }
    public Object getVar(String varName) {
        /* Deprecated: low-efficient or wrong operation
        Stack<VarDomain> t = (Stack<VarDomain>) varDomains.clone();
        while (t.size() != 0) {
            VarDomain v = t.pop();
            Object r = v.getVar(varName, false);
            if (r != null) {
                return r;
            }
        }
        for (VarDomain varDomain : varDomains) {
            Object r = varDomain.getVar(varName, false);
            if (r != null) {
                return r;
            }
        }*/
        for (int i = varDomains.size() - 1; i >= 0; i--) {
            Object r = varDomains.get(i).getVar(varName, false);
            if (r != null) {
                return r;
            }
        }
        return DataType.getDefaultNonType();
    }
    public void opVar(String varName, Function<Object, Object> operation) {
        opVar(varName, operation, false);
    }
    public void opVar(String varName, Function<Object, Object> operation, boolean contextAllow) {
        if (!contextAllow && varName.trim().startsWith("$")) {
            throw new OperationDeniedException();
        }
        for (VarDomain varDomain : varDomains) {
            if (varDomain.opVar(varName, operation)) {
                return ;
            }
        }
        throw new VarNotFoundException(varName);
    }
    public void saveVar(String varName, Object value) {
        saveVar(varName, value, false);
    }
    public void saveVar(String varName, Object value, boolean contextAllow) {
        //阻止用户操作上下文变量
        if (!contextAllow && varName.trim().startsWith("$")) {
            throw new OperationDeniedException();
        }
        VarDomain varDomain = varDomains.pop();
        varDomain.saveVar(varName, value);
        varDomains.push(varDomain);
    }
    @Override
    public String toString() {
        return Arrays.toString(varDomains.toArray());
    }
}